package cn.flying.cloud.base.common.utils.crypto;

import java.nio.charset.StandardCharsets;
import java.security.Security;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 国密算法 - SM3加密工具  杂凑算法 用来替换MD5、SHA-1、SHA-2
 * SM3为密码杂凑算法，采用密码散列(hash)）函数标准，用于替代MD5/SHA-1/SHA-2等国际算法，于2010年12月17日发布。
 * 是在 SHA-256基础上改进实现的一种算法，消息分组长度为512位，摘要值长度为256位，
 * 其中使用了异或、模、模加、移位、与、或、非运算，由填充、迭代过程、消息扩展和压缩函数所构成。
 * 在商用密码体系中，SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等。
 * 据国家密码管理局表示，其安全性及效率要高于MD5算法和SHA-1算法，与SHA-256相当。
 *
 * @author: admin
 * @date: 2025年01月21日 21:40
 * @version: 1.0
 */
public class SM3Util {
    private static final Logger logger = LoggerFactory.getLogger(SM3Util.class);

    // 添加安全提供者（SM2，SM3，SM4等加密算法，CBC、CFB等加密模式，PKCS7Padding等填充方式，不在Java标准库中，由BouncyCastleProvider实现）
    static {
        // 防止内存中出现多次BouncyCastleProvider的实例
        if (null == Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    /**
     * 通过密钥进行加密
     *
     * @param key  密钥
     * @param data 被加密的数据
     * @return
     * @explain 指定密钥进行加密
     */
    private static byte[] hmac(byte[] key, byte[] data) {
        KeyParameter keyParameter = new KeyParameter(key);
        SM3Digest digest = new SM3Digest();
        HMac mac = new HMac(digest);
        mac.init(keyParameter);
        mac.update(data, 0, data.length);
        byte[] result = new byte[mac.getMacSize()];
        mac.doFinal(result, 0);
        return result;
    }

    /**
     * 加密
     *
     * @param plainText
     * @param secret
     * @return
     */
    public static String encrypt(String plainText, String secret) {
        // 将字符串转换成byte数组
        byte[] data = plainText.getBytes(StandardCharsets.UTF_8);
        // 调用hash()
        byte[] cipherBytes = hmac(secret.getBytes(StandardCharsets.UTF_8), data);
        // 将返回的hash值转换成16进制字符串
        // 输出16进制字符串
        return Hex.toHexString(cipherBytes);

//        // 创建SM3Digest对象
//        SM3Digest sm3Digest = new SM3Digest();
//        // 初始化SM3计算
//        sm3Digest.update(plainText.getBytes(StandardCharsets.UTF_8), 0, plainText.length());
//        // 创建输出缓冲区
//        byte[] cipherBytes = new byte[sm3Digest.getDigestSize()];
//        // 计算SM3摘要
//        sm3Digest.doFinal(cipherBytes, 0);
    }

    /**
     * 判断源数据与加密数据是否一致
     *
     * @param plainText  原字符串
     * @param secret     密钥
     * @param cipherText 16进制字符串
     * @return 校验结果
     */
    public static boolean verify(String plainText, String secret, String cipherText) {
        String encrypt = encrypt(plainText, secret);
        return encrypt.equals(cipherText);
    }


//    public static void main(String[] args) {
//        String data = "国密算法：即我国自主研制的算法，摆脱对国外的技术过度依赖，国密即国家密码局认定的国产密码算法。以下是具体的对应关系：对称算法：AES、DES、SM4；非对称算法：RSA、SM2；摘要/杂凑算法：MD5、SHA-I、SM3";
//        String keySrc = UUID.randomUUID().toString();
//
//        String hex = Sm3Util.encrypt(data, keySrc);
//        System.out.println("参数:" + data);
//        System.out.println("密文:" + hex);
//        boolean verify = Sm3Util.verify(data, keySrc, hex);
//        System.out.println("验证结果：" + verify);
//    }

}
